package model.constraints.synthesized.attributes;


import java.util.ArrayList;
import java.util.Hashtable;

import model.constraints.inherited.Inters;

public abstract class SyntAttributesAbstract implements Cloneable {
	
	protected ArrayList<String> contextList = new ArrayList<String>();
	protected ArrayList<String> targetList = new ArrayList<String>();
	protected ArrayList<String> keyList = new ArrayList<String>();
	
	protected ArrayList<Boolean> c = new ArrayList<Boolean>(); //list true or false
	protected String dc = new String(); // one data element
	protected ArrayList<String> ds = new ArrayList<String>(); // one OR MORE data element
	protected ArrayList<Inters> inters = new ArrayList<Inters>(); // list of tuples <l1, l2> l1 for DS and l2 for DC
	protected String nodeName;	
	
	
	/***
	 * This function checks if has two inters equals
	 * @param newInters
	 * @param it
	 * @return if inters are equal return true
	 */
	public abstract Boolean containsEq (ArrayList<Inters> newInters, Inters it);
	
	public void setDsSize(int size){
		ds = new ArrayList<String>(size);
		for(int i=0;i<size;i++)
			ds.add(i, "");
	}
	
	public void addC(boolean element){
		c.add(element);
	}
	
	public void addInters (Inters element){
		inters.add(element);
	}
		
	public void concatInters (ArrayList<Inters> element){
		for (Inters c: element)
			inters.add(c);
	}

	public void setDc(String element){
		dc = element;
	}	

	public void setDs(ArrayList<String> a){
		ds = a;
	}
	
	public void setC(ArrayList<Boolean> a){
		c = a;
	}
	
	public void setDs(String element, int position){
		ds.set(position, element);
	}

	public void setDs(StringBuffer element, int position){
		ds.set(position, element.toString());
	}
		
	public void setInters(ArrayList<Inters> element){
		inters = element;
	}
	
	public void setContextList(ArrayList<String> c) {
		contextList = c;
	}

	public ArrayList<String> getContextList() {
		return contextList;
	}

	public void addContextList(String s) {
		contextList.add(s);
	}

	public boolean containsContextList(String s) {
		if (contextList.contains(s))
			return true;
		
		return false;
	}

	public void clearContextList(){
		contextList.clear();
	}

	public int sizeContextList(){
		return contextList.size();
	}

	public void setTargetList(ArrayList<String> t){
		targetList = t;
	}

	public ArrayList<String> getTargetList(){
		return targetList;
	}

	public void addTargetList(ArrayList<String> al){
		targetList.addAll(al);
	}

	public int sizeTargetList(){
		return targetList.size();
	}

	public boolean containsTargetList(String s){
		if (targetList.contains(s))
			return true;
		
		return false;
	}

	public void setKeyList(ArrayList<String> k){
		keyList = k;
	}

	public ArrayList<String> getKeyList(){
		return keyList;
	}


	public void addKeyList(String s){
		keyList.add(s);
	}

	public boolean containsKeyList(String s){
		if (keyList.contains(s))
			return true;
		
		return false;
	}

	public int sizeKeyList(){
		return keyList.size();
	}

	public boolean isEmpty(){
		if (c.isEmpty() && ds.isEmpty() && inters.isEmpty() && dc.isEmpty())
			return true;
		else
			return false;
	}

	public void addAll(SyntAttributesAbstract st){
		contextList.addAll(st.contextList);
		targetList.addAll(st.targetList);
		keyList.addAll(st.keyList);
	}

	public void addAllKey(SyntAttributesAbstract st){
		keyList.addAll(st.keyList);
	}

	public void addAllTarget(SyntAttributesAbstract st){
		targetList.addAll(st.targetList);
	}

	public void addAllContext(SyntAttributesAbstract st){
		contextList.addAll(st.contextList);
	}
	
	public void setNodeName(String node){
		nodeName = node;
	}
	
	public String getNodeName(){
		return nodeName;
	}
	
	public String getDc(){
		return dc;
	}
	
	public ArrayList<String> getDs(){
		return ds;
	}
	
	public ArrayList<Inters> getInters(){
		return inters;
	}
	
	public ArrayList<Boolean> getC(){
		return c;
	}	

	/**
	 * This function will join synthesized attributes with "inters" recovered
	 * @param aux is SyntAttributes
	 * @param htIntersXfd 
	 * @param dataPos
	 * @return
	 */
	public abstract SyntAttributesAbstract join (SyntAttributesAbstract aux, Hashtable<String,ArrayList<Inters>> htIntersXfd, String dataPos);		
	
	public String toString(){
		StringBuffer strbuff = new StringBuffer();
		if(!ds.isEmpty())
			strbuff.append("ds = " + toStringAux(ds)+", ");
		if(!dc.isEmpty())
			strbuff.append("dc = <" + dc + ">, ");
		if(!inters.isEmpty())
			strbuff.append("inters = {" + toStringInters(inters) + "}, ");
		if(!c.isEmpty())
			strbuff.append("c = " + toStringAux(c));
		
		String str = strbuff.toString();
		
		return str;
	}
	
	/**
	 * This function print ArrayList 
	 * @param ArrayList type Boolean or String
	 * @return String
	 */
	@SuppressWarnings("rawtypes")
	public String toStringAux(ArrayList list) {
		StringBuffer strbuff = new StringBuffer("<");
		
		for(int i=0;i<list.size();i++)
			strbuff.append(list.get(i).toString()).append(", ");
		
		strbuff.append(">");
		
		return strbuff.toString();
	}
	
	public String toStringInters(ArrayList<Inters> list){
		StringBuffer strbuff = new StringBuffer();
		
		for(Inters aux: list) {
			strbuff.append("<");
			strbuff.append(aux.getDs().toString()).append(", ");
			strbuff.append(aux.getDc().toString());
			strbuff.append(",<" + aux.getCondVector().toString() + ">");
			strbuff.append(">, ");
		}
		
		return strbuff.toString();
	}		
}